package com.xmtlxx.web.controller.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.xmtlxx.web.controller.wms.service.IInventoryPlanService;
import com.xmtlxx.wms.domain.Inventory;
import com.xmtlxx.wms.domain.InventoryDtl;
import com.xmtlxx.wms.domain.InventoryPlan;
import com.xmtlxx.wms.domain.Store;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xmtlxx.common.core.domain.PageQuery;
import com.xmtlxx.common.core.domain.entity.SysDept;
import com.xmtlxx.common.core.page.TableDataInfo;
import com.xmtlxx.common.exception.ServiceException;
import com.xmtlxx.common.helper.LoginHelper;
import com.xmtlxx.common.tengbo.PushDatasUtil;
import com.xmtlxx.common.tengbo.vo.InventoryDatasDtlVo;
import com.xmtlxx.common.tengbo.vo.InventoryPlanDatasVo;
import com.xmtlxx.common.utils.DateUtils;
import com.xmtlxx.common.utils.StringUtils;
import com.xmtlxx.system.mapper.SysDeptMapper;
import com.xmtlxx.wms.domain.bo.*;
import com.xmtlxx.wms.domain.vo.*;
import com.xmtlxx.wms.mapper.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 盘点计划Service业务层处理
 *
 * @author xmtlxx
 * @date 2022-08-15
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class InventoryPlanServiceImpl implements IInventoryPlanService {

    private final InventoryPlanMapper baseMapper;

    private final InventoryDtlMapper inventoryDtlMapper;

    private final InventoryMapper inventoryMapper;

    private final SysDeptMapper sysDeptMapper;

    private final StoreMapper storeMapper;

    private final LocatorMapper locatorMapper;

    /**
     * 查询盘点计划
     *
     * @param id 盘点计划主键
     * @return 盘点计划
     */
    @Override
    public InventoryPlanVo queryById(String id){
        //return baseMapper.selectVoById(id);
        InventoryPlanVo vo = baseMapper.selectInventoryPlanVoByID(id);
        InventoryDtlBo bo = new InventoryDtlBo();
        bo.setInventoryId(id);

        //vo.setItems(inventoryDtlMapper.selectInventoryDtlList(bo));
        List<InventoryDtlVo> proList = inventoryDtlMapper.selectNewInventoryDtlList(id);
        int num = 0;
        for(InventoryDtlVo inventoryDtlVo : proList){
            if("1".equals(inventoryDtlVo.getStatus())){
                num = num+1;
            }
        }
        vo.setRfidNums(num);
        vo.setItems(proList);
        return vo;
    }

    /**
     * 查询盘点计划列表
     *
     * @param bo 盘点计划
     * @return 盘点计划
     */
    @Override
    public TableDataInfo<InventoryPlanVo> queryPageList(InventoryPlanBo bo, PageQuery pageQuery) {
       // LambdaQueryWrapper<InventoryPlan> lqw = buildQueryWrapper(bo);
       // Page<InventoryPlanVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        Page<InventoryPlanVo> result = baseMapper.selectPageInventoryPlanList(pageQuery.build(), bo);
        return TableDataInfo.build(result);
    }

    /**
     * 查询盘点计划列表
     *
     * @param bo 盘点计划
     * @return 盘点计划
     */
    @Override
    public List<InventoryPlanVo> queryList(InventoryPlanBo bo) {
       // LambdaQueryWrapper<InventoryPlan> lqw = buildQueryWrapper(bo);
       // return baseMapper.selectVoList(lqw);
        return baseMapper.selectInventoryPlanList(bo);
    }

    private LambdaQueryWrapper<InventoryPlan> buildQueryWrapper(InventoryPlanBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<InventoryPlan> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getInventoryNo()), InventoryPlan::getInventoryNo, bo.getInventoryNo());
        lqw.eq(StringUtils.isNotBlank(bo.getStoreId()), InventoryPlan::getStoreId, bo.getStoreId());
        lqw.eq(StringUtils.isNotBlank(bo.getInventoryUser()), InventoryPlan::getInventoryUser, bo.getInventoryUser());
        lqw.eq(StringUtils.isNotBlank(bo.getOperator()), InventoryPlan::getOperator, bo.getOperator());
        lqw.eq(bo.getOperateTime() != null, InventoryPlan::getOperateTime, bo.getOperateTime());
        lqw.eq(StringUtils.isNotBlank(bo.getChecker()), InventoryPlan::getChecker, bo.getChecker());
        lqw.eq(StringUtils.isNotBlank(bo.getCheckStatus()), InventoryPlan::getCheckStatus, bo.getCheckStatus());
        lqw.eq(bo.getCheckTime() != null, InventoryPlan::getCheckTime, bo.getCheckTime());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), InventoryPlan::getStatus, bo.getStatus());
        lqw.eq(bo.getDeptId() != null, InventoryPlan::getDeptId, bo.getDeptId());
        lqw.eq(StringUtils.isNotBlank(bo.getCreateBy()), InventoryPlan::getCreateBy, bo.getCreateBy());
        lqw.between(params.get("beginCreateTime") != null && params.get("endCreateTime") != null,
            InventoryPlan::getCreateTime ,params.get("beginCreateTime"), params.get("endCreateTime"));
        lqw.eq(StringUtils.isNotBlank(bo.getUpdateBy()), InventoryPlan::getUpdateBy, bo.getUpdateBy());
        lqw.between(params.get("beginUpdateTime") != null && params.get("endUpdateTime") != null,
            InventoryPlan::getUpdateTime ,params.get("beginUpdateTime"), params.get("endUpdateTime"));
        lqw.eq(StringUtils.isNotBlank(bo.getDelFlag()), InventoryPlan::getDelFlag, bo.getDelFlag());
        return lqw;
    }

    /**
     * 新增盘点计划
     *
     * @param bo 盘点计划
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public InventoryPlanVo insertByBo(InventoryPlanBo bo) {
        InventoryPlanVo vo = new InventoryPlanVo();
        InventoryPlan add = BeanUtil.toBean(bo, InventoryPlan.class);
        validEntityBeforeSave(add);

        //填充UUID
        add.setId(IdUtil.simpleUUID());
        add.setDelFlag("0");
        add.setInventoryNo(getNo());

        Long books = 0l;
        Long nums = 0l;
        Long result = 0l;
        List<InventoryDtl> dtls = new ArrayList<>();
        if(bo.getItems() != null && bo.getItems().size() > 0){
            for(InventoryDtlVo item : bo.getItems()){
                InventoryDtl dtl = BeanUtil.toBean(item, InventoryDtl.class);
                dtl.setId(IdUtil.simpleUUID());
                dtl.setInventoryId(add.getId());
                dtl.setStatus("0");
                dtls.add(dtl);
                books += item.getBooks() == null ? 0 : item.getBooks();
                nums += item.getNums() == null ? 0 : item.getNums();
                result += item.getResults() == null ? 0 : item.getResults();
            }
        }

        add.setBooks(books);
        add.setNums(nums);
        add.setResults(result);
        if(bo.getLocatorIds() != null && bo.getLocatorIds().length > 0){
            add.setLocators(String.join(",",bo.getLocatorIds()));
        }


        boolean flag = baseMapper.insert(add) > 0;

        if(dtls != null && dtls.size() > 0){
            inventoryDtlMapper.insertBatch(dtls);
        }

        if (flag) {
            bo.setId(add.getId());
            BeanUtil.copyProperties(add,vo);
        }

        //数据推送
        pushDatas(add,dtls);

        return vo;
    }

    public void pushDatas(InventoryPlan plan,List<InventoryDtl> dtls){
        InventoryPlanDatasVo data = new InventoryPlanDatasVo();
        BeanUtil.copyProperties(plan,data);
        if(plan.getDeptId() != null){
            SysDept dept = sysDeptMapper.selectById(plan.getDeptId());
            data.setDeptNo(dept.getDeptCode());
            data.setDeptName(dept.getDeptName());
        }
        Store store = storeMapper.selectById(plan.getStoreId());
        data.setStoreName(store.getName());

        List<InventoryDatasDtlVo> items = BeanUtil.copyToList(dtls,InventoryDatasDtlVo.class);
        data.setItems(items);

        PushDatasUtil.pushInventorysDatas(data);
    }

    /**
     * 修改盘点计划
     *
     * @param bo 盘点计划
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(InventoryPlanBo bo) {
        InventoryPlan update = BeanUtil.toBean(bo, InventoryPlan.class);
        validEntityBeforeSave(update);
        Long books = 0l;
        Long nums = 0l;
        Long result = 0l;
        List<InventoryDtl> dtls = new ArrayList<>();
        if(bo.getItems() != null && bo.getItems().size() > 0){
            for(InventoryDtlVo item : bo.getItems()){
                InventoryDtl dtl = BeanUtil.toBean(item, InventoryDtl.class);
                if(StringUtils.isEmpty(dtl.getId())){
                    dtl.setId(IdUtil.simpleUUID());
                    dtl.setStatus("0");
                }
                Long dtlResult = (item.getNums() == null ? 0 : item.getNums())-(item.getBooks() == null ? 0 : item.getBooks());
                dtl.setResults(dtlResult);
                books += item.getBooks() == null ? 0 : item.getBooks();
                nums += item.getNums() == null ? 0 : item.getNums();
                result += dtlResult;

                //设置库存最新盘点时间
                if(update.getStatus().equals("3")){
                    InventoryVo inventoryVo = inventoryMapper.selectInventoryVoByID(dtl.getStockId());
                    if(inventoryVo != null){
                        inventoryVo.setLastTime(new Date());
                        Inventory inventory = new Inventory();
                        BeanUtil.copyProperties(inventoryVo,inventory);
                        inventoryMapper.insertOrUpdate(inventory);
                    }
//                    dtl.setStatus("1");
                }
                dtls.add(dtl);
            }
        }
        update.setBooks(books);
        update.setNums(nums);
        update.setResults(result);

        if(bo.getLocatorIds() != null && bo.getLocatorIds().length > 0){
            update.setLocators(String.join(",",bo.getLocatorIds()));
        }

        //盘点时间
        if(update.getStatus().equals("1") || update.getStatus().equals("3") ){
            update.setInventoryUser(LoginHelper.getUsername());
            update.setOperateTime(new Date());
            update.setOperator(LoginHelper.getNickname());
        }

        if(dtls != null && dtls.size() > 0){
            inventoryDtlMapper.insertOrUpdateBatch(dtls);
        }
        return baseMapper.updateById(update) > 0;
    }

    @Override
    public Boolean updateStatusByBo(InventoryPlanBo bo) {
        InventoryPlan update = BeanUtil.toBean(bo, InventoryPlan.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     *
     * @param entity 实体类数据
     */
    private void validEntityBeforeSave(InventoryPlan entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除盘点计划
     *
     * @param ids 需要删除的盘点计划主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<String> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    public InventoryPlanVo initBeanByBoxNo(String boxNo) {
        if(StringUtils.isEmpty(boxNo)){
            throw new ServiceException("扫码异常，请重新扫码！");
        }
        String[] ignoreProperties = {"id","createBy","createTime","updateBy","updateTime"};

        InventoryPlanVo vo = new InventoryPlanVo();
        vo.setInventoryNo(getNo());
        vo.setStatus("0");
        InventoryBo bo = new InventoryBo();
        bo.setBoxNo(boxNo);
        vo.setBooks(0l);
        vo.setNums(0l);
        vo.setResults(0l);
        List<InventoryVo> inventoryVos = inventoryMapper.selectInventoryList(bo);

        if(inventoryVos != null && inventoryVos.size() > 0){
            Long  nums = inventoryVos.stream().mapToLong(item-> item.getNums()).sum();
            InventoryVo enty = inventoryVos.get(0);
            BeanUtil.copyProperties(enty,vo,ignoreProperties);
            vo.setBooks(nums);
            vo.setNums(nums);
            vo.setInventoryUser(LoginHelper.getUsername());
            vo.setOperator(LoginHelper.getNickname());
            vo.setDeptId(LoginHelper.getDeptId());

            LocatorVo locatorVo = locatorMapper.selectLocatorVoByID(enty.getLocatorId());
            if(locatorVo != null){
                vo.setCabinetGroupId(locatorVo.getCabinetGroupId());
                vo.setCabinetId(locatorVo.getCabinetId());
            }

            List<InventoryDtlVo> dtls = inventoryVos.stream().map(item->{
                InventoryDtlVo dtl = new InventoryDtlVo();
                BeanUtil.copyProperties(item,dtl,ignoreProperties);
                dtl.setStockId(item.getId());
                dtl.setBooks(item.getNums());
                dtl.setResults(0l);
                return dtl;
            }).collect(Collectors.toList());
            vo.setItems(dtls);

        }

        return vo;
    }

    public String getNo(){
        Long maxNumObject = baseMapper.selectCountAlls();
        String num = "";
        String todayStr = DateUtils.date2String(new Date(), "yyMMdd");

        if (maxNumObject == null) {
            num = todayStr + "000001";
        } else {
            String maxnumStr = "00000" + maxNumObject.toString();
            String maxnumNo = maxnumStr.substring(maxnumStr.length() - 6, maxnumStr.length());
            String nextnumNo = StringUtils.nextNo(maxnumNo, 6);
            num = todayStr + nextnumNo;
        }
        return num;
    }

    @Override
    public List<InventoryDtlVo> queryPlanProList(String id) {
        return baseMapper.queryPlanProList(id);
    }

    @Override
    public List<InventoryPlanProExportVo> getInventoryPlanExportList(InventoryPlanProExportBo bo) {
        return baseMapper.getInventoryPlanExportList(bo);
    }

    @Override
    public List<InventoryPlanStatisticsExportVo> getInventoryPlanStatisticsExportList(InventoryPlanProExportBo bo) {
        return baseMapper.getInventoryPlanStatisticsExportList(bo);
    }

    @Override
    public Boolean deletePlanProByPnos(InventoryPlanDeleteBo bo) {
        Boolean result = baseMapper.deletePlanProByPnos(bo);
        //更新盘点单的信息 账面数据，已盘数据，未盘数据
        baseMapper.updatePlanBooksByNo(bo.getInventoryNo());
        baseMapper.updatePlanNumsByNo(bo.getInventoryNo());
        baseMapper.updatePlanResultByNo(bo.getInventoryNo());
        return result;
    }


}
